package com.seguriapp.alerts.gwt.client;

import java.util.List;

import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.AsyncHandler;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.cellview.client.RowStyles;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.seguriapp.alerts.gwt.client.activity.AlertsListActivity;
import com.seguriapp.alerts.gwt.client.activity.AlertsListActivity.Display;
import com.seguriapp.common.gwt.client.UtilClientValidations;
import com.seguriapp.common.gwt.client.celltable.HyperLinkColumn;
import com.seguriapp.common.gwt.client.celltable.SeguriAppCellTable;
import com.seguriapp.common.gwt.client.pagination.SearchPagination;
import com.seguriapp.common.gwt.client.searchfilter.SearchFilter;
import com.seguriapp.entities.Alert;

public class AlertsListPage extends Composite implements Display {

  private static final String NEW_ALERTS = " nueva(s) alerta(s)";

  private static AlertsListPageUiBinder uiBinder = GWT.create(AlertsListPageUiBinder.class);

  interface AlertsListPageUiBinder extends UiBinder<Widget, AlertsListPage> {
  }

  @UiField
  protected HTMLPanel alertsGridPanel;
  @UiField
  protected SearchFilter searchFilter;
  @UiField
  protected InlineLabel noDataLabel;
  @UiField
  protected SearchPagination pagination;
  @UiField
  protected Anchor showNewAlertsLink;

  private CellTable<Alert> alertsGrid;
  private TextColumn<Alert> namesColumn;
  private TextColumn<Alert> lastNameColumn;
  private TextColumn<Alert> dniColumn;
  private TextColumn<Alert> dateColumn;
  private Column<Alert, String> viewDetailColumn;
  private AlertsListActivity presenter;

  public AlertsListPage() {
    initWidget(uiBinder.createAndBindUi(this));
    iniciarColumnas();
    initiateGridData();
    inicializarHandlers();
  }

  public void setPresenter(final AlertsListActivity presenter) {
    this.presenter = presenter;
  }

  private void iniciarColumnas() {
    namesColumn = new TextColumn<Alert>() {

      @Override
      public String getValue(final Alert alert) {
        return alert.getNames();
      }
    };

    lastNameColumn = new TextColumn<Alert>() {

      @Override
      public String getValue(final Alert alert) {
        return alert.getLastNames();
      }
    };

    dniColumn = new TextColumn<Alert>() {

      @Override
      public String getValue(final Alert alert) {
        return alert.getDni();
      }
    };

    dateColumn = new TextColumn<Alert>() {

      @Override
      public String getValue(final Alert alert) {
        if (alert.getDate() == null) {
          return "-";
        }
        return UtilClientValidations.DATE_VIEW_FORMAT.format(alert.getDate());
      }
    };

    viewDetailColumn = new HyperLinkColumn<Alert>() {

      @Override
      public String getValue(final Alert alert) {
        return "";
      }

      @Override
      public void render(final Context context, final Alert alert, final SafeHtmlBuilder sb) {
        setTooltip("Ver Detalle");
        setStyle("detailsIcon");
        super.render(context, alert, sb);
      }

    };

    namesColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    lastNameColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    dniColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    viewDetailColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    dateColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

    namesColumn.setSortable(true);
    lastNameColumn.setSortable(true);
    dniColumn.setSortable(true);
    dateColumn.setSortable(true);

    viewDetailColumn.setFieldUpdater(new FieldUpdater<Alert, String>() {

      public void update(final int index, final Alert alert, final String value) {
        presenter.goToAlertDetailsPage(alert);
      }
    });
  }

  private void inicializarHandlers() {

    AsyncDataProvider<Alert> dataProvider = new AsyncDataProvider<Alert>() {

      @Override
      protected void onRangeChanged(HasData<Alert> display) {

        // Get the ColumnSortInfo from the table.
        final ColumnSortList sortList = alertsGrid.getColumnSortList();
        if (sortList.size() > 0) {
          presenter.setAscending(sortList.get(0).isAscending());
          if (sortList.get(0).getColumn().equals(namesColumn)) {
            presenter.setColumnSort("names");
          } else if (sortList.get(0).getColumn().equals(lastNameColumn)) {
            presenter.setColumnSort("lastNames");
          } else if (sortList.get(0).getColumn().equals(dniColumn)) {
            presenter.setColumnSort("dni");
          } else if (sortList.get(0).getColumn().equals(dateColumn)) {
            presenter.setColumnSort("date");
          }
          presenter.updateAlertsList();
        }
      }
    };

    dataProvider.addDataDisplay(alertsGrid);

    // Add a ColumnSortEvent.AsyncHandler to connect sorting to the
    // AsyncDataPRrovider.
    AsyncHandler columnSortHandler = new AsyncHandler(alertsGrid);
    alertsGrid.addColumnSortHandler(columnSortHandler);

  }

  private void generateTable() {
    alertsGrid = new SeguriAppCellTable<Alert>();
    alertsGrid.addColumn(namesColumn, "Nombres");
    alertsGrid.addColumn(lastNameColumn, "Apellidos");
    alertsGrid.addColumn(dniColumn, "DNI");
    alertsGrid.addColumn(dateColumn, "Fecha y Hora");
    alertsGrid.addColumn(viewDetailColumn, "Detalle");
    alertsGrid.setColumnWidth(namesColumn, "30%");
    alertsGrid.setColumnWidth(lastNameColumn, "30%");
    alertsGrid.setColumnWidth(dniColumn, "20%");
    alertsGrid.setColumnWidth(viewDetailColumn, "20%");
    alertsGrid.setColumnWidth(dateColumn, "20%");
  }

  private void initiateGridData() {
    generateTable();
    alertsGridPanel.clear();
    alertsGridPanel.add(alertsGrid);
  }

  public void setGridData(final List<Alert> alertsList) {
    noDataLabel.setVisible(false);
    alertsGridPanel.setVisible(true);
    alertsGrid.setRowData(0, alertsList);
    alertsGrid.setRowCount(alertsList.size(), true);
    alertsGrid.setRowStyles(new RowStyles<Alert>() {

      public String getStyleNames(final Alert row, final int rowIndex) {
        return row.isNewAlert() ? "newAlert" : null;
      }
    });
    final Timer t = new Timer() {

      @Override
      public void run() {
        alertsGrid.setRowStyles(null);
        alertsGrid.setRowData(0, alertsList);
        alertsGrid.setRowCount(alertsList.size(), true);
      }
    };

    // Schedule the timer to run in 3 seconds.
    t.schedule(3000);
  }

  public void setPagination(final long currentPage, final long totalPages, final long maxPages) {
    pagination.setPagination(currentPage, totalPages, maxPages);
  }

  public SearchFilter getSearchFilter() {
    return searchFilter;
  }

  public SearchPagination getPagination() {
    return pagination;
  }

  public void showNoDataMessage() {
    noDataLabel.setVisible(true);
    alertsGridPanel.setVisible(false);
  }

  public void showNewAlertsLink(final int alertsCount) {
    if (alertsCount > 0) {
      showNewAlertsLink.setText(alertsCount + NEW_ALERTS);
      showNewAlertsLink.setVisible(true);
    } else {
      showNewAlertsLink.setVisible(false);
    }
  }

  @UiHandler("showNewAlertsLink")
  protected void onShowNewAlertsLinkClick(final ClickEvent event) {
    showNewAlertsLink.setVisible(false);
    presenter.showNewAlerts();
  }

}
